package com.crayon.utils
{
	import flash.utils.ByteArray;
	
	/**
	 * 字符串一些常用方法。
	 * <p>
	 * 字符串相关的常用的方法，例如判断是否相等、忽略空格等。
	 * </p>
	 */
	public class StringUtil
	{
		
		/**
		 * 比较指定两个字符是否相等
		 * @param	char1	字符串一
		 * @param	char2	字符串二
		 * @return			是否相等
		 */
		public static function equals(char1:String, char2:String):Boolean
		{
			return char1 == char2;
		}
		
		/**
		 * 忽略大小字母比较字符是否相等
		 * @param	char1	字符串一
		 * @param	char2	字符串二
		 * @return			是否相等
		 */
		public static function equalsIgnoreCase(char1:String, char2:String):Boolean
		{
			return char1.toLowerCase() == char2.toLowerCase();
		}
		
		/**
		 * 是否是数值字符串
		 * @param	char	指定字符串
		 * @return			是否是数字
		 */
		public static function isNumber(char:String):Boolean
		{
			if (!char)
			{
				return false;
			}
			return !isNaN(Number(char));
		}
		
		/**
		 * 是否为合法 Email
		 * @param	char	指定字符串
		 * @return			是否合法
		 */
		public static function isEmail(char:String):Boolean
		{
			var pattern:RegExp = /(\w|[_.\-])+@((\w|-)+\.)+\w{2,4}+/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否是 Double 型数据
		 * @param	char	指定字符串
		 * @return			是否是 Double 型
		 */
		public static function isDouble(char:String):Boolean
		{
			var pattern:RegExp = /^[+\-]?\d+(\.\d+)?$/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否是整数
		 * @param	char	指定字符串
		 * @return			是否是整数
		 */
		public static function isInteger(char:String):Boolean
		{
			var pattern:RegExp = /^[-\+]?\d+$/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否是英文字符（包括大小写）
		 * @param	char	指定字符串
		 * @return			是否是英文字符
		 */
		public static function isEnglish(char:String):Boolean
		{
			var pattern:RegExp = /^[A-Za-z]+$/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否是中文
		 * @param	char	指定字符串
		 * @return			是否是中文
		 */
		public static function isChinese(char:String):Boolean
		{
			var pattern:RegExp = /^[\u0391-\uFFE5]+$/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否是双字节
		 * @param	char	指定字符串
		 * @return			是否是双字节
		 */
		public static function isDoubleChar(char:String):Boolean
		{
			var pattern:RegExp = /^[^\x00-\xff]+$/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否包含中文
		 * @param	char	指定字符串
		 * @return			是否包含中文
		 */
		public static function hasChineseChar(char:String):Boolean
		{
			var pattern:RegExp = /[^\x00-\xff]/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 检测字符长度，判断是否达到指定的长度
		 * @param	char	指定字符串
		 * @param	length	指定的长度
		 * @return			是否达到指定的长度
		 */
		public static function hasAccountChar(char:String, length:uint):Boolean
		{
			if (!char)
			{
				return false;
			}
			var pattern:RegExp = new RegExp("^[a-zA-Z0-9][a-zA-Z0-9_-]{0," + length + "}$", "");
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否是 url 地址
		 * @param	char	指定字符串
		 * @return			是否是 url 地址
		 */
		public static function isURL(char:String):Boolean
		{
			if (!char)
			{
				return false;
			}
			char = char.toLowerCase();
			var pattern:RegExp = /^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/;
			return checkChar(char, pattern);
		}
		
		/**
		 * 是否为空白
		 * @param	char	指定字符串
		 * @return			是否为空白
		 */
		public static function isWhitespace(char:String):Boolean
		{
			switch (char)
			{
				case " ": 
				case "\t": 
				case "\r": 
				case "\n": 
				case "\f": 
					return true;
				default: 
					return false;
			}
		}
		
		/**
		 * 检测指定字符串是否匹配指定模式
		 * @param	char	指定字符串
		 * @param	pattern	指定模式
		 * @return			是否匹配
		 */
		public static function checkChar(char:String, pattern:RegExp):Boolean
		{
			if (!char)
			{
				return false;
			}
			char = trim(char);
			return pattern.test(char);
		}
		
		/**
		 * 去左右空格
		 * @param	char	指定字符串
		 */
		public static function trim(char:String):String
		{
			if (!char)
			{
				return null;
			}
			return rtrim(ltrim(char));
		}
		
		/**
		 * 去左空格
		 * @param	char	指定字符串
		 */
		public static function ltrim(char:String):String
		{
			if (!char)
			{
				return null;
			}
			var pattern:RegExp = /^\s*/;
			return char.replace(pattern, "");
		}
		
		/**
		 * 去右空格
		 * @param	char	指定字符串
		 */
		public static function rtrim(char:String):String
		{
			if (!char)
			{
				return null;
			}
			var pattern:RegExp = /\s*$/;
			return char.replace(pattern, "");
		}
		
		/**
		 * 是否为前缀字符串
		 * @param	char	指定字符串
		 * @param	prefix	指定前缀
		 * @return			是否符合
		 */
		public static function beginsWith(char:String, prefix:String):Boolean
		{
			return (prefix == char.substring(0, prefix.length));
		}
		
		/**
		 * 是否为后缀字符串
		 * @param	char	指定字符串
		 * @param	prefix	指定后缀
		 * @return			是否符合
		 */
		public static function endsWith(char:String, suffix:String):Boolean
		{
			return (suffix == char.substring(char.length - suffix.length));
		}
		
		/**
		 * 去除指定字符串
		 * @param	char	指定字符串
		 * @param	remove	需要去除的字符串
		 * @return			新的字符串
		 */
		public static function remove(char:String, remove:String):String
		{
			return replace(char, remove, "");
		}
		
		/**
		 * 字符串替换
		 * @param	char		指定字符串
		 * @param	replace		需要替换的字符串
		 * @param	replaceWith	需要替换的字符串的宽度
		 * @return				新的字符串
		 */
		public static function replace(char:String, replace:String, replaceWith:String):String
		{
			return char.split(replace).join(replaceWith);
		}
		
		/**
		 * utf16 转 utf8 编码
		 * @param	char	指定字符串
		 * @return			新的字符串
		 */
		public static function utf16to8(char:String):String
		{
			var out:Array = [];
			var length:uint = char.length;
			for (var i:uint = 0; i < length; i++)
			{
				var c:int = char.charCodeAt(i);
				if (c >= 0x0001 && c <= 0x007F)
				{
					out[i] = char.charAt(i);
				}
				else if (c > 0x07FF)
				{
					out[i] = String.fromCharCode(0xE0 | ((c >> 12) & 0x0F), 0x80 | ((c >> 6) & 0x3F), 0x80 | ((c >> 0) & 0x3F));
				}
				else
				{
					out[i] = String.fromCharCode(0xC0 | ((c >> 6) & 0x1F), 0x80 | ((c >> 0) & 0x3F));
				}
			}
			return out.join('');
		}
		
		/**
		 * utf8 转 utf16 编码
		 * @param	char	指定字符串
		 * @return			新的字符串
		 */
		public static function utf8to16(char:String):String
		{
			var out:Array = [];
			var length:uint = char.length;
			var i:uint = 0;
			var char2:int;
			var char3:int;
			while (i < length)
			{
				var c:int = char.charCodeAt(i++);
				switch (c >> 4)
				{
					case 0: 
					case 1: 
					case 2: 
					case 3: 
					case 4: 
					case 5: 
					case 6: 
					case 7: 
						// 0xxxxxxx
						out[out.length] = char.charAt(i - 1);
						break;
					case 12: 
					case 13: 
						// 110x xxxx   10xx xxxx
						char2 = char.charCodeAt(i++);
						out[out.length] = String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
						break;
					case 14: 
						// 1110 xxxx  10xx xxxx  10xx xxxx
						char2 = char.charCodeAt(i++);
						char3 = char.charCodeAt(i++);
						out[out.length] = String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
						break;
				}
			}
			return out.join('');
		}
		
		/**
		 * 获取字符串的字节长度。
		 * @param string 字符串。
		 * @param charSet 表示用于解释字节的字符集的字符串。例如：utf-8、gb2312。
		 * @return 字节长度。
		 */
		public static function getByteLength(string:String, charSet:String = "utf-8"):uint
		{
			var bytes:ByteArray = new ByteArray();
			bytes.writeMultiByte(string, charSet);
			return bytes.length;
		}
		
		/**
		 * 根据指定的字节长度截取字符串。
		 * @param input 要截取的字符串。
		 * @param limitByteLength 要限制的字节长度。
		 * @param charSet 表示用于解释字节的字符集的字符串。例如：utf-8、gb2312。
		 * @return 截取后的字符串。
		 */
		public static function substrInByte(input:String, limitByteLength:uint, charSet:String = "gb2312"):String
		{
			var bytes:ByteArray = new ByteArray();
			bytes.writeMultiByte(input, charSet);
			if (bytes.length <= limitByteLength)
			{
				return input;
			}
			
			bytes.position = 0;
			return bytes.readMultiByte(limitByteLength, charSet);
		}
		
		/**
		 * 右修剪字符串。
		 * @param input 需要修剪的字符串。
		 * @param targetByteLength 修剪后的字节长度。
		 * @param suffixShort 字符串过短时要补上的尾词（会重复补上，直到输出结果满足 targetByteLength 长度为止）。
		 * @param suffixLong 字符串过长时要补上的尾词（只补上一个）。
		 * @param charSet 表示用于解释字节的字符集的字符串。例如：utf-8、gb2312。
		 * @return 修剪后的字符串。
		 */
		public static function rTrimString(input:String, targetByteLength:uint, suffixShort:String, suffixLong:String, charSet:String = "gb2312"):String
		{
			var output:String;
			var inputBytes:ByteArray = new ByteArray();
			inputBytes.writeMultiByte(input, charSet);
			
			var offset:int = inputBytes.length - targetByteLength;
			if (offset == 0) // 正好相等
			{
				output = input;
			}
			else if (offset < 0) // 过短
			{
				var i:int = Math.abs(offset) / getByteLength(suffixShort, charSet);
				while (i--)
				{
					input += suffixShort;
				}
				output = input;
			}
			else if (offset > 0) // 过长
			{
				inputBytes.position = 0;
				var suffixLongByteLength:uint = getByteLength(suffixLong, charSet);
				if (targetByteLength > suffixLongByteLength)
				{
					output = inputBytes.readMultiByte(targetByteLength - suffixLongByteLength, charSet) + suffixLong;
				}
				else
				{
					output = inputBytes.readMultiByte(targetByteLength, charSet);
				}
			}
			
			return output;
		}
	}
}